package com.bookmanger.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bookmanger.common.result.Result;
import com.bookmanger.common.utils.StringUtils;
import com.bookmanger.common.utils.UserIdThreadLocal;
import com.bookmanger.entity.Book;
import com.bookmanger.entity.Order;
import com.bookmanger.entity.User;
import com.bookmanger.entity.dto.BookBorrowDTO;
import com.bookmanger.entity.dto.BookSearchDTO;
import com.bookmanger.entity.dto.OrderDTO;
import com.bookmanger.entity.select.OrderBookListDTO;
import com.bookmanger.entity.vo.ListForm;
import com.bookmanger.entity.vo.OrderBookListVo;
import com.bookmanger.mapper.OrderMapper;
import com.bookmanger.mapper.UserMapper;
import com.bookmanger.service.BookBorrowService;
import com.bookmanger.service.BookService;
import com.bookmanger.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author huangfuhao
 * @Date 2024/11/6
 */
@Service
@Slf4j
public class BookBorrowServiceImpl extends ServiceImpl<OrderMapper, Order> implements BookBorrowService {

    @Resource
    private UserService userService;

    @Resource
    private BookService bookService;

    @Override
    @Transactional
    public Result<BookBorrowDTO> borrow(Order order) {
        //传来的对象所拥有的参数：bookId
        //小程序用户申请借阅图书，生成订单，订单状态为“预约（4）”

        log.info("{}", order);

        //根据userId查看用户信息，判断其是否拥有借书的权限
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getId, UserIdThreadLocal.getUserId());
        User user = userService.getOne(wrapper);

        //判断用户是否存在
        if (user == null) {
            return Result.error("用户不存在");
        }

        //判断用户是否拥有借书的权限
        int banned = user.getBanned();
        if (banned == 1) {
            return Result.error("用户被禁止借书，请先归还图书");
        }

        //查看订单库中该用户是否已借阅过该本书
        LambdaQueryWrapper<Order> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.eq(Order::getUserId, order.getUserId()).eq(Order::getBookId, order.getBookId()).ne(Order::getStatus, 1);
        Order one = this.getOne(orderWrapper);
        if (one != null) {
            return Result.error("不可重复借阅同一本书籍");
        }

        //先查看图书库存是否充足
        LambdaQueryWrapper<Book> bookWrapper = new LambdaQueryWrapper<>();
        bookWrapper.eq(Book::getId, order.getBookId());
        Book book = bookService.getOne(bookWrapper);
        int amount = book.getAmount();
        if (amount <= 0) {
            return Result.error("该书库存不足");
        }

        // 即可生成借书订单
        // 扣除书本库存-1，
        amount--;
        boolean update = bookService.lambdaUpdate().eq(Book::getId, order.getBookId()).set(Book::getAmount, amount).update();
        if (!update) {
            return Result.error("图书库存扣除失败，服务器异常");
        }

        //获取当前日期，以及21天后的日期，并存储进order表当中
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MILLISECOND, 0);

        LocalDateTime start = LocalDateTime.now();
        LocalDateTime end = start.plusDays(21);

        order.setUserId(UserIdThreadLocal.getUserId());
        order.setStartTime(start);
        order.setEndTime(end);
        order.setStatus(4); //设置状态为“预约（4）”

        boolean save = this.save(order);
        if (!save) {
            return Result.error("借书失败，服务器异常");
        }


        return Result.success(BeanUtil.copyProperties(order, BookBorrowDTO.class));
    }


    /**
     * 用户还书
     *
     * @param order
     * @return
     */
    @Override
    @Transactional
    public Result<BookBorrowDTO> restore(Order order) {
        //获取借阅记录id
        Long id = order.getId();

        //拿到借阅记录
        Order order1 = this.getById(id);

        //拿到图书id
        Long bookId = order1.getBookId();

        //将对应的图书库存+1
        LambdaUpdateWrapper<Book> bookWrapper = new LambdaUpdateWrapper<>();
        bookWrapper.eq(Book::getId, bookId);
        bookWrapper.setSql("amount = amount + 1");
        bookService.update(bookWrapper);

        //修改借阅记录的“归还未确认（3）”状态
        boolean update = lambdaUpdate().eq(Order::getId, id).set(Order::getStatus, 3).update();
        if (!update) {
            return Result.error(null);
        }

        //拿到用户id
        Long userId = order1.getUserId();
        //查看用户是否还存在未归还且过期的书籍
        LambdaQueryWrapper<Order> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.eq(Order::getUserId, userId).eq(Order::getStatus, 2);
        List<Order> list = this.list(orderWrapper);

        //若无则设置借阅权限为可借阅
        if (list.isEmpty()) {
            userService.update().eq("id", userId).set("banned", 0).update();
        }
        order.setStatus(3);
        return Result.success(BeanUtil.copyProperties(order, BookBorrowDTO.class));
    }

    /**
     * 查看用户借阅记录
     *
     * @return
     */
    @Override
    public Result<List<BookBorrowDTO>> record() {
        Long userId = UserIdThreadLocal.getUserId();
        List<Order> list = lambdaQuery().eq(Order::getUserId, userId).list();
        List<BookBorrowDTO> collect = list.stream().map(order -> {
            Book book = bookService.getById(order.getBookId());
            BookBorrowDTO bookBorrowDTO = BeanUtil.copyProperties(book, BookBorrowDTO.class);
            bookBorrowDTO.setId(order.getId());
            bookBorrowDTO.setBookId(order.getBookId());
            bookBorrowDTO.setUserId(order.getUserId());
            bookBorrowDTO.setStatus(order.getStatus());
            bookBorrowDTO.setStartTime(order.getStartTime());
            bookBorrowDTO.setEndTime(order.getEndTime());
            bookBorrowDTO.setCreateTime(order.getCreateTime());
            bookBorrowDTO.setUpdateTime(order.getUpdateTime());
            return bookBorrowDTO;
        }).collect(Collectors.toList());
        return Result.success(collect);
    }

    @Override
    public Result<ListForm<OrderBookListVo>> getOrderList(OrderBookListDTO orderBookListDTO) {
        log.info("orderBookListDTO: {}", orderBookListDTO);
        // 计算分页参数
        int page = orderBookListDTO.getPage() != null ? orderBookListDTO.getPage() : 1;
        int size = orderBookListDTO.getSize() != null ? orderBookListDTO.getSize() : 10;
        int offset = (page - 1) * size;

        // 查询数据列表
        List<OrderBookListVo> orderList = baseMapper.getOrderBookList(orderBookListDTO, offset, size);

        // 查询总记录数
        Long totalSize = baseMapper.getOrderBookListCount(orderBookListDTO);
        Long totalPages = (long) Math.ceil((double) totalSize / size);

        // 封装结果
        ListForm<OrderBookListVo> listForm = new ListForm<>();
        listForm.setPage(page);
        listForm.setSize(size);
        listForm.setTotalPages(totalPages);
        listForm.setTotalSize(totalSize);
        listForm.setListData(orderList);

        return Result.success(listForm);
    }


    /**
     * 管理员通过借阅预约
     *
     * @param order
     * @return
     */
    @Override
    public Result<BookBorrowDTO> passBorrow(Order order) {
        log.info("管理员通过预约:{}", order);
        //1.获取预约的订单
        Long orderId = order.getId();

        Order order1 = lambdaQuery().eq(Order::getId, orderId).one();

        if (order1 == null) {
            return Result.error("通过失败，订单不存在");
        }
        //设置订单状态为0
        order1.setStatus(0);

        //根据id更新订单
        //2.将订单状态修改为“未归还（0）”
        boolean update = updateById(order1);
        if (!update) {
            return Result.error("通过失败，数据异常");
        }
        //3.返回订单详情
        return Result.success(BeanUtil.copyProperties(order1, BookBorrowDTO.class));

    }


    /**
     * 管理员确认归还
     *
     * @param order
     * @return
     */
    @Override
    public Result<BookBorrowDTO> passRestore(Order order) {
        log.info("管理员同意归还:{}", order);
        //1.获取预约的订单
        Long orderId = order.getId();

        Order order1 = lambdaQuery().eq(Order::getId, orderId).one();

        if (order1 == null) {
            return Result.error("通过失败，订单不存在");
        }
        //设置订单状态为0
        order1.setStatus(1);

        //根据id更新订单
        //2.将订单状态修改为“已归还归还（1）”
        boolean update = updateById(order1);
        if (!update) {
            return Result.error("通过失败，数据异常");
        }
        //3.返回订单详情
        return Result.success(BeanUtil.copyProperties(order1, BookBorrowDTO.class));
    }


    /**
     * 管理员拒绝归还
     */
    @Override
    public Result<BookBorrowDTO> refuseRestore(Order order) {
        log.info("管理员拒绝归还:{}", order);
        //1.获取预约的订单
        Long orderId = order.getId();

        Order order1 = lambdaQuery().eq(Order::getId, orderId).one();

        if (order1 == null) {
            return Result.error("通过失败，订单不存在");
        }
        //设置订单状态为0
        order1.setStatus(5);

        //根据id更新订单
        //2.将订单状态修改为“归还失败（5）”
        boolean update = updateById(order1);
        if (!update) {
            return Result.error("通过失败，数据异常");
        }
        //3.返回订单详情
        return Result.success(BeanUtil.copyProperties(order1, BookBorrowDTO.class));
    }


    /**
     * 管理员查询图书相关订单
     *
     * @param order
     * @return
     */
    @Override
    public Result<List<OrderDTO>> orders(Order order) {
        Long bookId = order.getBookId();
        if (bookId == null) {
            return Result.error("图书不存在");
        }


        List<Order> list = lambdaQuery().eq(Order::getBookId, bookId).list();

        if (list==null||list.isEmpty()){
            return Result.success(new ArrayList<>());
        }


        List<OrderDTO> orderDTOS = new ArrayList<>();
        List<Object> collect = list.stream().map(item -> {

            User user = userService.getById(item.getUserId());
            Book book = bookService.getById(item.getBookId());

            OrderDTO orderDTO = new OrderDTO();
            BeanUtil.copyProperties(item,orderDTO);
            orderDTO.setUserName(user.getUsername());
            orderDTO.setBookName(book.getBookName());
            orderDTOS.add(orderDTO);

            return item;
        }).collect(Collectors.toList());

        return Result.success(orderDTOS);

    }

}
